package org.openkanban.server.cometd;

import java.util.HashMap;
import java.util.Map;

import org.cometd.Bayeux;
import org.cometd.Client;
import org.cometd.Extension;
import org.cometd.Message;
import org.cometd.RemoveListener;
import org.mortbay.cometd.AbstractBayeux;
import org.openkanban.server.domain.User;
import org.openkanban.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author msa
 * 
 */
@Component
public class SecurityPolicyDefaultImpl extends AbstractBayeux.DefaultPolicy implements Extension, RemoveListener {

    private static final String AUTHENTICATION_DATA = "authenticationData";

    @Autowired
    private UserService userService;

    @Override
    public boolean canHandshake(Message message) {
	Map<String, Object> ext = message.getExt(false);
	if (ext == null)
	    return false;

	// Be sure the client does not cheat us
	ext.remove(AUTHENTICATION_DATA);

	@SuppressWarnings("unchecked")
	Map<String, Object> authentication = (Map<String, Object>) ext.get("authentication");
	if (authentication == null)
	    return false;

	User user = new User(authentication.get("user").toString(), authentication.get("pwd").toString());
	boolean loggedIn = userService.logIn(user);
	if (loggedIn == false)
	    return false;

	// Store the authentication result in the message for later
	// processing
	ext.put(AUTHENTICATION_DATA, loggedIn);

	return true;
    }

    @Override
    public Message sendMeta(Client remote, Message responseMessage) {
	if (Bayeux.META_HANDSHAKE.equals(responseMessage.getChannel())) {
	    Message requestMessage = responseMessage.getAssociated();

	    Map<String, Object> requestExt = requestMessage.getExt(false);
	    Object authenticationData = requestExt.get("authenticationData");
	    if (authenticationData != null) {
		// Authentication successful

		// Link authentication data to the remote client

		// Be notified when the remote client disappears
		remote.addListener(this);
	    } else {
		// Authentication failed

		// Add extra fields to the response
		Map<String, Object> responseExt = responseMessage.getExt(true);
		Map<String, Object> authentication = new HashMap<String, Object>();
		responseExt.put("authentication", authentication);
		authentication.put("failed", true);

		// Tell the client to stop any further attempt
		// to handshake
		Map<String, Object> advice = new HashMap<String, Object>();
		advice.put(Bayeux.RECONNECT_FIELD, Bayeux.NONE_RESPONSE);
		responseMessage.put(Bayeux.ADVICE_FIELD, advice);
	    }
	}
	return responseMessage;
    }

    @Override
    public void removed(String clientId, boolean timeout) {

    }

    @Override
    public Message rcv(Client from, Message message) {
	// TODO Auto-generated method stub
	return null;
    }

    @Override
    public Message rcvMeta(Client from, Message message) {
	// TODO Auto-generated method stub
	return null;
    }

    @Override
    public Message send(Client from, Message message) {
	// TODO Auto-generated method stub
	return null;
    }

}
